#include "dispatchtaskservice.h"

DispatchTaskService *DispatchTaskService::_DTS = NULL;
std::mutex DispatchTaskService::m;
std::queue<BKSEvent*> DispatchTaskService::_rsp_evs_queue;
DispatchTaskService*DispatchTaskService::getInstance()
{
    if(_DTS){
        return _DTS;
    }

    m.lock();

    _DTS = new DispatchTaskService();

    if(_DTS){
        m.unlock();
        return _DTS;
    }

    m.unlock();

    return _DTS;
}

void DispatchTaskService::subscribe(u32 eid, BKSHandler *handler)
{   
    auto _ev_handlers_Map_iter = _ev_handlers_Map.find(eid);
    if(_ev_handlers_Map_iter == _ev_handlers_Map.end()){
        _ev_handlers_Map[eid].push_back(handler);
        LOG_DEBUG("DispatchTaskService::subscribe ---> %s subscribe eid [%d]", handler->get_name().c_str(), eid);
        return;
    }

    auto _handlers_iter = std::find(_ev_handlers_Map_iter->second.begin(), _ev_handlers_Map_iter->second.end(), handler);
    if(_handlers_iter == _ev_handlers_Map_iter->second.end()){
        _ev_handlers_Map_iter->second.push_back(handler);
        LOG_DEBUG("DispatchTaskService::subscribe ---> %s subscribe eid [%d]", handler->get_name().c_str(), eid);
    }

    return;
}

void DispatchTaskService::unsubscribe(u32 eid, BKSHandler *handler)
{
    auto _ev_handlers_Map_iter = _ev_handlers_Map.find(eid);
    if(_ev_handlers_Map_iter != _ev_handlers_Map.end()){
        auto _handlers_iter = std::find(_ev_handlers_Map_iter->second.begin(), _ev_handlers_Map_iter->second.end(), handler);
        if(_handlers_iter != _ev_handlers_Map_iter->second.end())
        {
            _ev_handlers_Map_iter->second.erase(_handlers_iter);
            LOG_DEBUG("DispatchTaskService::subscribe ---> %s unsubscribe eid [%d]", handler->get_name().c_str(), eid);
        }
    }
    
    return;
}

BOOL DispatchTaskService::open()
{
    if(!_stop.load()){
        _pool = thread_pool_init();
        _stop.store(TRUE);
    }

    return _pool == NULL ? FALSE : TRUE;
}

void DispatchTaskService::close()
{
    if(_stop.load() && _pool){   
        _stop.store(FALSE);
        thread_pool_destroy(_pool);
    }

    return;
}

i32 DispatchTaskService::enqueue(BKSEvent *ev)
{
    if(!ev){   
        LOG_WARN("DispatchTaskService::enqueue ---> ev is null.");
        return -1;
    }

    thread_task_t *task = thread_task_alloc(0);
    task->handler = DispatchTaskService::service;
    task->ctx = ev;

    return thread_task_post(_pool, task);
}

void DispatchTaskService::service(void *arg)
{   
    DispatchTaskService *_DTS = NULL;
    _DTS = DispatchTaskService::getInstance();
    BKSEvent *ev = (BKSEvent *)arg;
    if(ev){   
        _DTS->process(ev);
        LOG_INFO("DispatchTaskService::servic ---> servicing ...");
    }

    return;
}

std::vector<BKSEvent*> DispatchTaskService::process(BKSEvent *ev)
{   
    ConnSession *cs = (ConnSession*)ev->get_arg();
    std::vector<BKSEvent*>_Rsp_evs;
    if(!ev){   
        LOG_WARN("DispatchTaskService::process ---> ev is null.");
        return _Rsp_evs;
    }

    u32 eid = ev->get_eid();
    auto _ev_handlers_Map_iter = _ev_handlers_Map.find(eid);
    if(_ev_handlers_Map_iter == _ev_handlers_Map.end()){
        LOG_WARN("DispatchTaskService::process ---> not find ev handler.");
        return _Rsp_evs;
    }

    for(auto _handlers_iter = _ev_handlers_Map_iter->second.begin(); _handlers_iter != _ev_handlers_Map_iter->second.end(); _handlers_iter ++){
        auto rspev = (*_handlers_iter)->handle(ev);
        LOG_DEBUG("DispatchTaskService::process ---> handler name: %s", (*_handlers_iter)->get_name().c_str());
        if(rspev){
            rspev->dump(std::cout);
        }
        else{
            rspev = new ErrorEv();
        }
        rspev->set_arg(cs);
        {   
            std::lock_guard<std::mutex> lk(m);
            _rsp_evs_queue.push(rspev);
            _Rsp_evs.push_back(rspev);
        }
    }

    return _Rsp_evs;
}

BKSEvent* DispatchTaskService::praseToReqEvent(char *_read_msg_buf, u32 read_msg_len, void *arg){
    ConnSession *cs = (ConnSession*)arg;
    BKSEvent *reqev = NULL;

    if(!cs){
        LOG_ERROR("DispatchTaskService::praseToReqEvent ---> cs is null.");
        return reqev;
    }

    u32 eid = cs->eid;

    if(eid == EVENT_MOBILE_GET_CODE_REQ){
        mobile_request mreq;
        if(mreq.ParseFromArray(_read_msg_buf, read_msg_len)){

            LOG_DEBUG("DispatchTaskService::praseToReqEvent ---> mobile request mobile phone: %s", mreq.mobile().c_str());
            reqev = new MobileCodeReqEv(mreq.mobile());
            reqev->set_arg(cs);

            return reqev;
        }
    }
    else if(eid == EVENT_LOGIN_REQ){
        login_request logreq;
        if(logreq.ParseFromArray(_read_msg_buf, read_msg_len)){

            LOG_DEBUG("DispatchTaskService::praseToReqEvent ---> mobile request mobile phone: %s and icode: %d", logreq.mobile().c_str(), logreq.icode());
            reqev = new LoginReqEv(logreq.mobile(), logreq.icode());
            reqev->set_arg(cs);
            return reqev;
        }
    }
    else if(eid == EVENT_RECHARGE_REQ){

    }

    //...
    
    return NULL;
}


